{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "unicode.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [
        "oL9KopJirB2g"
      ],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "oL9KopJirB2g"
      },
      "source": [
        "##### Copyright 2018 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "SKaX3Hd3ra6C",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "AXH1bmUctMld"
      },
      "source": [
        "# Юникод-строки\n",
        "\n",
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://www.tensorflow.org/tutorials/load_data/unicode\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\" />Смотрите на TensorFlow.org</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/ru/tutorials/load_data/unicode.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Запустите в Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/ru/tutorials/load_data/unicode.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />Изучайте код на GitHub</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs/site/ru/tutorials/load_data/unicode.ipynb\"><img src=\"https://www.tensorflow.org/images/download_logo_32px.png\" />Скачайте ноутбук</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fj66ZXAzrJC2",
        "colab_type": "text"
      },
      "source": [
        "Note: Вся информация в этом разделе переведена с помощью русскоговорящего Tensorflow сообщества на общественных началах. Поскольку этот перевод не является официальным, мы не гарантируем что он на 100% аккуратен и соответствует [официальной документации на английском языке](https://www.tensorflow.org/?hl=en). Если у вас есть предложение как исправить этот перевод, мы будем очень рады увидеть pull request в [tensorflow/docs](https://github.com/tensorflow/docs) репозиторий GitHub. Если вы хотите помочь сделать документацию по Tensorflow лучше (сделать сам перевод или проверить перевод подготовленный кем-то другим), напишите нам на [docs-ru@tensorflow.org list](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-ru)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "LrHJrKYis06U"
      },
      "source": [
        "## Введение\n",
        "\n",
        "Модели обрабатывающие естественные языки, часто имеют дело с разными языками и разными наборами символов. * Unicode * - это стандартная система кодирования, которая используется для представления символов практически всех языков. Каждый символ кодируется с использованием уникального целого числа [кодовой точки](https://en.wikipedia.org/wiki/Code_point) между `0` и` 0x10FFFF`. *Юникод-строка* - это последовательность из нуля или более таких кодовых точек.\n",
        "\n",
        "Это руководство показывает как представлять юникод-строки в Tensorflow и манипулировать ими используя юникодовские эквиваленты стандартной строковой. Она выделяет юникод-строки в токены на основе обнаружения скрипта."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "OIKHl5Lvn4gh",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "try:\n",
        "  # %tensorflow_version существует только в Colab.\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "  pass\n",
        "import tensorflow as tf"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "n-LkcI-vtWNj"
      },
      "source": [
        "## Тип данных `tf.string`\n",
        "\n",
        "Базовый TensorFlow `tf.string` `dtype` позволяет вам строить тензоры байт-строк.\n",
        "Юникод-строки по умолчанию в кодировке utf-8."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "3yo-Qv6ntaFr",
        "colab": {}
      },
      "source": [
        "tf.constant(u\"Спасибо 😊\")"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "2kA1ziG2tyCT"
      },
      "source": [
        "Тензор `tf.string` может содержать байт-строки различной длины поскольку байт-строки обрабатываются как отдельные единицы. Длина строки не включена в размерность тензора.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "eyINCmTztyyS",
        "colab": {}
      },
      "source": [
        "tf.constant([u\"Добро\", u\"пожаловать!\"]).shape"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "jsMPnjb6UDJ1"
      },
      "source": [
        "Замечание: При использовании python при конструировании строк обработка юникода отличается между v2 и v3. В v2, юникод-строки отмечены префиксом \"u\", как и выше. В v3, строки закодированы в юникоде по умолчанию."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "hUFZ7B1Lk-uj"
      },
      "source": [
        "## Представление Юникода\n",
        "\n",
        "Есть два стандартных способа представления юникод-строк в TensorFlow:\n",
        "\n",
        "* `string` скаляр — где последовательность кодовых точек закодирована с использованием [набора символов](https://ru.wikipedia.org/wiki/%D0%9D%D0%B0%D0%B1%D0%BE%D1%80_%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%D0%BE%D0%B2).\n",
        "* `int32` вектор — где каждая позиция содержит единственную кодовую точку.\n",
        "\n",
        "Например, следующие три значения все представляют юникод-строку `\"语言处理\"` (что значит \"обработка языка\" на китайском):"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "cjQIkfJWvC_u",
        "colab": {}
      },
      "source": [
        "# Юникод-строки, представленные как UTF-8 закодированные строки скаляры.\n",
        "text_utf8 = tf.constant(u\"语言处理\")\n",
        "text_utf8"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "yQqcUECcvF2r",
        "colab": {}
      },
      "source": [
        "# Юникод-строки представленные как UTF-16-BE закодированные строки скаляры.\n",
        "text_utf16be = tf.constant(u\"语言处理\".encode(\"UTF-16-BE\"))\n",
        "text_utf16be"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "ExdBr1t7vMuS",
        "colab": {}
      },
      "source": [
        "# Юникод строки представленные как векторы юникодовских кодовых точек.\n",
        "text_chars = tf.constant([ord(char) for char in u\"语言处理\"])\n",
        "text_chars"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "B8czv4JNpBnZ"
      },
      "source": [
        "### Конвертация между представлениями\n",
        "\n",
        "TensorFlow предоставляет операции для конвертации между этими различными представлениями:\n",
        "\n",
        "* `tf.strings.unicode_decode`: Конвертирует закодированную строку скаляр в вектор кодовых точек.\n",
        "* `tf.strings.unicode_encode`: Конвертирует вектор кодовых точек в закодированную строку скаляр.\n",
        "* `tf.strings.unicode_transcode`: Конвертирует строку скаляр в другую кодировку."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "qb-UQ_oLpAJg",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_decode(text_utf8,\n",
        "                          input_encoding='UTF-8')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "kEBUcunnp-9n",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_encode(text_chars,\n",
        "                          output_encoding='UTF-8')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "0MLhWcLZrph-",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_transcode(text_utf8,\n",
        "                             input_encoding='UTF8',\n",
        "                             output_encoding='UTF-16-BE')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "QVeLeVohqN7I"
      },
      "source": [
        "### Размерности пакета\n",
        "\n",
        "При декодировании нескольких строк размер символов в каждой строке может не совпадать, Возвращаемый результат это [`tf.RaggedTensor`](../../guide/ragged_tensor.ipynb), где длина самого внутреннего измерения меняется в зависимости от количества символов в каждой строке:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "N2jVzPymr_Mm",
        "colab": {}
      },
      "source": [
        "# Пакет юнокод-строк каждая из которых представлена в виде строки в юникод-кодировке.\n",
        "batch_utf8 = [s.encode('UTF-8') for s in\n",
        "              [u'hÃllo',  u'What is the weather tomorrow',  u'Göödnight', u'😊']]\n",
        "batch_chars_ragged = tf.strings.unicode_decode(batch_utf8,\n",
        "                                               input_encoding='UTF-8')\n",
        "for sentence_chars in batch_chars_ragged.to_list():\n",
        "  print(sentence_chars)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "iRh3n1hPsJ9v"
      },
      "source": [
        "Вы можете использовать `tf.RaggedTensor` напрямую, или конвертировать его в плотный `tf.Tensor` с паддингом или в `tf.SparseTensor` используя методы `tf.RaggedTensor.to_tensor` и `tf.RaggedTensor.to_sparse`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "yz17yeSMsUid",
        "colab": {}
      },
      "source": [
        "batch_chars_padded = batch_chars_ragged.to_tensor(default_value=-1)\n",
        "print(batch_chars_padded.numpy())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "kBjsPQp3rhfm",
        "colab": {}
      },
      "source": [
        "batch_chars_sparse = batch_chars_ragged.to_sparse()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "GCCkZh-nwlbL"
      },
      "source": [
        "При кодировании нескольких строк одинаковой длины  `tf.Tensor` может быть использован в качестве входных данных:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "_lP62YUAwjK9",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_encode([[99, 97, 116], [100, 111, 103], [ 99, 111, 119]],\n",
        "                          output_encoding='UTF-8')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "w58CMRg9tamW"
      },
      "source": [
        "При кодировании нескольких строк различной длины нужно использовать `tf.RaggedTensor` в качестве входных данных:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "d7GtOtrltaMl",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_encode(batch_chars_ragged, output_encoding='UTF-8')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "T2Nh5Aj9xob3"
      },
      "source": [
        "Если у вас тензор с несколькими строками с паддингом или в разреженном формате, то ковертируйте его в `tf.RaggedTensor` перед вызовом `unicode_encode`:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "R2bYCYl0u-Ue",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_encode(\n",
        "    tf.RaggedTensor.from_sparse(batch_chars_sparse),\n",
        "    output_encoding='UTF-8')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "UlV2znh_u_zm",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_encode(\n",
        "    tf.RaggedTensor.from_tensor(batch_chars_padded, padding=-1),\n",
        "    output_encoding='UTF-8')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "hQOOGkscvDpc"
      },
      "source": [
        "## Операции юникода"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "NkmtsA_yvMB0"
      },
      "source": [
        "### Длина символа\n",
        "\n",
        "Операция `tf.strings.length` имеет параметр `unit`, который показывает как должна быть посчитана длина.  По умолчанию размер `unit` равен `\"BYTE\"`, но он может быть установлен с другим значением, таким как `\"UTF8_CHAR\"` или `\"UTF16_CHAR\"`, чтобы определить число кодовых точек в каждой закодированой `string`."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "1ZzMe59mvLHr",
        "colab": {}
      },
      "source": [
        "# Заметьте что последний символ занимает до 4 байтов в UTF8.\n",
        "thanks = u'Thanks 😊'.encode('UTF-8')\n",
        "num_bytes = tf.strings.length(thanks).numpy()\n",
        "num_chars = tf.strings.length(thanks, unit='UTF8_CHAR').numpy()\n",
        "print('{} bytes; {} UTF-8 characters'.format(num_bytes, num_chars))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "fHG85gxlvVU0"
      },
      "source": [
        "### Подстроки символов\n",
        "\n",
        "Аналогично у операции `tf.strings.substr` есть параметр \"`unit`\", который используется для определения смещений параметров \"`pos`\" и \"`len`\"."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "WlWRLV-4xWYq",
        "colab": {}
      },
      "source": [
        "# по умолчанию: unit='BYTE'. С len=1, мы возвращаем один байт.\n",
        "tf.strings.substr(thanks, pos=7, len=1).numpy()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "JfNUVDPwxkCS",
        "colab": {}
      },
      "source": [
        "# Установив unit='UTF8_CHAR', мы возвратим один символ, размер которого в этом случае\n",
        "#  4 байта.\n",
        "print(tf.strings.substr(thanks, pos=7, len=1, unit='UTF8_CHAR').numpy())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "zJUEsVSyeIa3"
      },
      "source": [
        "### Разбиение юникод-строки\n",
        "\n",
        "Операция `tf.strings.unicode_split` разбивает юникод-строки в подстроки отдельных символов:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "dDjkh5G1ejMt",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_split(thanks, 'UTF-8').numpy()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "HQqEEZEbdG9O"
      },
      "source": [
        "### Смещения байтов для символов\n",
        "\n",
        "Чтобы выровнять тензор символа порожденный `tf.strings.unicode_decode` с оригинальной строкой, полезно знать смещение начала каждого символа.  Метод `tf.strings.unicode_decode_with_offsets` аналогичен `unicode_decode`, за исключением того, что он возвращает второй тензор содержащий размер отступа от начала для каждого символа."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "Cug7cmwYdowd",
        "colab": {}
      },
      "source": [
        "codepoints, offsets = tf.strings.unicode_decode_with_offsets(u\"🎈🎉🎊\", 'UTF-8')\n",
        "\n",
        "for (codepoint, offset) in zip(codepoints.numpy(), offsets.numpy()):\n",
        "  print(\"At byte offset {}: codepoint {}\".format(offset, codepoint))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "2ZnCNxOvx66T"
      },
      "source": [
        "## Юникод скрипты"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "nRRHqkqNyGZ6"
      },
      "source": [
        "Каждая кодовая точка принадлежит коллекции символов известной как [система письма](https://en.wikipedia.org/wiki/Script_%28Unicode%29) .  Система письма полезна для определения того, какому языку может принадлежать символ. Например, зная что 'Б' из кириллицы указывает на то, что современный текст содержащий этот символ скорее всего из славянского языка, такого как русский или украинский.\n",
        "\n",
        "В TensorFlow есть операция `tf.strings.unicode_script` для определения какой системе письма принадлежит данная кодовая точка. Коды систем письма это `int32` числа соответствующие [Международным компонентам для\n",
        "юникода](http://site.icu-project.org/home) (ICU) [`UScriptCode`](http://icu-project.org/apiref/icu4c/uscript_8h.html) значения.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "K7DeYHrRyFPy",
        "colab": {}
      },
      "source": [
        "uscript = tf.strings.unicode_script([33464, 1041])  # ['芸', 'Б']\n",
        "\n",
        "print(uscript.numpy())  # [17, 8] == [USCRIPT_HAN, USCRIPT_CYRILLIC]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "2fW992a1lIY6"
      },
      "source": [
        "Операция `tf.strings.unicode_script` может быть также применена к многомерному `tf.Tensor`s или кодовым точкам `tf.RaggedTensor`:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "uR7b8meLlFnp",
        "colab": {}
      },
      "source": [
        "print(tf.strings.unicode_script(batch_chars_ragged))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "mx7HEFpBzEsB"
      },
      "source": [
        "## Пример: Простая сегментация\n",
        "\n",
        "Сегментация это задача разбиения текста на словоподобные юниты. Часто это легко когда испольуются символы пробела для отделения слов, но некоторые языки (например китайский и японский) не используют пробелы, а некоторые языки (например немецкий) содержат длинные соединения, которые должны быть разделены для анализа их значений. В веб текстах, различные языки и скрипты часто перемешаны между собой , как например в \"NY株価\" (New York Stock Exchange).\n",
        "\n",
        "Мы можем выполнить грубую сегментацию (без реализации каких-либо моделей ML), используя изменения систем письма для приблизительного определения границ слов. Это будет работать для строк наподобие вышеприведенного примера \"NY株価\". Это также будет работать для всех языков, которые используют пробелы, так как символы пробела в различных системах письма все классифицируются как USCRIPT_COMMON, специальный код, который отличается от кода любого актуального текста."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "grsvFiC4BoPb",
        "colab": {}
      },
      "source": [
        "# dtype: string; shape: [num_sentences]\n",
        "#\n",
        "# Предложения для обработки.  Поменяйте эту строку чтобы попробовать разные входные данные!\n",
        "sentence_texts = [u'Hello, world.', u'世界こんにちは']"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "CapnbShuGU8i"
      },
      "source": [
        "Сперва мы декодируем предложения в кодовые точки, и определим идентификатор системы письма для каждого символа."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "ReQVcDQh1MB8",
        "colab": {}
      },
      "source": [
        "# dtype: int32; shape: [num_sentences, (num_chars_per_sentence)]\n",
        "#\n",
        "# sentence_char_codepoint[i, j] кусок кода для j-го символа\n",
        "# в i-м предложении.\n",
        "sentence_char_codepoint = tf.strings.unicode_decode(sentence_texts, 'UTF-8')\n",
        "print(sentence_char_codepoint)\n",
        "\n",
        "# dtype: int32; shape: [num_sentences, (num_chars_per_sentence)]\n",
        "#\n",
        "# sentence_char_scripts[i, j] код системы письма для j-го символа в\n",
        "# i-м предложении.\n",
        "sentence_char_script = tf.strings.unicode_script(sentence_char_codepoint)\n",
        "print(sentence_char_script)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "O2fapF5UGcUc"
      },
      "source": [
        "Далее мы используем эти идентификаторы систем письма чтобы определить куда должны быть добавлены границы слов.  Мы добавим границу слова в начало каждого предложения и для каждого символа чья система письма отличается от предыдущего символа:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "7v5W6MOr1Rlc",
        "colab": {}
      },
      "source": [
        "# dtype: bool; shape: [num_sentences, (num_chars_per_sentence)]\n",
        "#\n",
        "# sentence_char_starts_word[i, j] является True если j'th символ в i'th\n",
        "# предложении является началом слова.\n",
        "sentence_char_starts_word = tf.concat(\n",
        "    [tf.fill([sentence_char_script.nrows(), 1], True),\n",
        "     tf.not_equal(sentence_char_script[:, 1:], sentence_char_script[:, :-1])],\n",
        "    axis=1)\n",
        "\n",
        "# dtype: int64; shape: [num_words]\n",
        "#\n",
        "# word_starts[i] это индекс символа начинающего i-е слово (в\n",
        "# выпрямленном списке символов всех предложений).\n",
        "word_starts = tf.squeeze(tf.where(sentence_char_starts_word.values), axis=1)\n",
        "print(word_starts)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "LAwh-1QkGuC9"
      },
      "source": [
        "Затем мы можем использовать эти сдвиги от начала для построения `RaggedTensor` содержащего список слов из всех пакетов:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "bNiA1O_eBBCL",
        "colab": {}
      },
      "source": [
        "# dtype: int32; shape: [num_words, (num_chars_per_word)]\n",
        "#\n",
        "# word_char_codepoint[i, j] is the кодовая точка для j-го символа в\n",
        "# i-м слове.\n",
        "word_char_codepoint = tf.RaggedTensor.from_row_starts(\n",
        "    values=sentence_char_codepoint.values,\n",
        "    row_starts=word_starts)\n",
        "print(word_char_codepoint)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "66a2ZnYmG2ao"
      },
      "source": [
        "И наконец, мы можем сегментировать кодовые точки слов `RaggedTensor` обратно в предложения:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "NCfwcqLSEjZb",
        "colab": {}
      },
      "source": [
        "# dtype: int64; shape: [num_sentences]\n",
        "#\n",
        "# sentence_num_words[i] число слов в i'th предложении.\n",
        "sentence_num_words = tf.reduce_sum(\n",
        "    tf.cast(sentence_char_starts_word, tf.int64),\n",
        "    axis=1)\n",
        "\n",
        "# dtype: int32; shape: [num_sentences, (num_words_per_sentence), (num_chars_per_word)]\n",
        "#\n",
        "# sentence_word_char_codepoint[i, j, k] это кодовая точка для k-го символа\n",
        "# в j-м слове i-го предложения.\n",
        "sentence_word_char_codepoint = tf.RaggedTensor.from_row_lengths(\n",
        "    values=word_char_codepoint,\n",
        "    row_lengths=sentence_num_words)\n",
        "print(sentence_word_char_codepoint)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "xWaX8WcbHyqY"
      },
      "source": [
        "Чтобы сделать итоговый результат проще для чтения, мы можем закодировать его обратно в UTF-8 строки:"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "HSivquOgFr3C",
        "colab": {}
      },
      "source": [
        "tf.strings.unicode_encode(sentence_word_char_codepoint, 'UTF-8').to_list()"
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}